package com.pictavore.message;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.*;
import java.lang.Object.*;

/**
 *
 * @author dvenable
 */
@Singleton
public class Messenger {
    Hashtable<MessageType, Vector<MessageListener>> listeners = new Hashtable<MessageType, Vector<MessageListener>>();
    Hashtable<MessageType, Vector<MessageResponder>> responders = new Hashtable<MessageType, Vector<MessageResponder>>();
    Stack<Message> queue = new Stack<Message>();

    public void addListener(MessageType type, MessageListener ml) {
        _addListener(type, ml);
    }

    public void addResponder(MessageType type, MessageResponder mrsp) {
        _addResponder(type, mrsp);
    }

    public void sendMessage(MessageType type, Object sender, Object... params) {
        send(type, sender, params);
    }

    public Object sendRequest(MessageType type, Object sender, Object... params) {
        return request(type, sender, params);
    }

    public Messenger() {
    }

    void _addResponder(MessageType type, MessageResponder mrsp) {
        if (!responders.containsKey(type)) {
            responders.put(type, new Vector<MessageResponder>());
        }
        responders.get(type).add(mrsp);
    }

    void _addListener(MessageType type, MessageListener mrsp) {
        if (!listeners.containsKey(type)) {
            listeners.put(type, new Vector<MessageListener>());
        }
        listeners.get(type).add(mrsp);
    }

    public Object request(MessageType type, Object sender, Object... params) {
        for (MessageResponder ml : getResponders(type)) {
            Object obj = ml.respond(type, sender, params);
            if (obj != null) {
                return obj;
            }
        }
        return null;
    }

    public Vector<MessageListener> getListeners(MessageType type) {
        Vector<MessageListener> ret = null;
        if (listeners.containsKey(type)) {
            ret = listeners.get(type);
        }

        if (ret == null) {
            ret = new Vector<MessageListener>();
        }
        return ret;
    }

    public Vector<MessageResponder> getResponders(MessageType type) {
        Vector<MessageResponder> ret = null;
        if (responders.containsKey(type)) {
            ret = responders.get(type);
        }

        if (ret == null) {
            ret = new Vector<MessageResponder>();
        }
        return ret;
    }
    private Boolean isSending = false;

    public void send(MessageType type, Object sender, Object... params) {
        queue.push(new Message(type, sender, params));

        if (isSending == false) {
            isSending = true;
            while (!queue.empty()) {
                Message msg = queue.pop();
                for (MessageListener ml : getListeners(msg.getType())) {
                    ml.onMessage(msg);
                }
            }
            isSending = false;
        }
    }
}
